iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
JavaScript

Javascript網頁程式管理系統系列 第 25

day 25 javascript連結github程式碼網頁程式管理系統

  • 分享至 

  • xImage
  •  

今天是第二十五天我們可以寫一個 javascript 連結github程式碼網頁程式管理系統,以下是我的程式碼

  • 查看其 GitHub 儲存庫的列表
  • 瀏覽指定儲存庫的提交紀錄
  • 管理(建立/更新)儲存庫的 issue

技術堆疊:

  1. HTML + JavaScript + Bootstrap:建立簡單的前端界面
  2. GitHub REST API:與 GitHub 互動
  3. OAuth 認證:透過 OAuth 令牌來管理私人儲存庫的權限

應用流程:

  1. 使用者登入 GitHub,並允許應用存取其資料。
  2. 系統顯示使用者的儲存庫列表。
  3. 使用者點選某個儲存庫後,顯示該儲存庫的提交紀錄。
  4. 使用者可以查看和管理該儲存庫的 issue(包括建立新 issue)。

步驟 1:建立 OAuth 認證流程

首先,你需要在 GitHub Developer Settings 中建立一個 OAuth 應用程式。獲得以下資訊:

  • Client ID
  • Client Secret
  • 設置重定向 URI,例如 http://localhost:3000/callback

用戶點擊登入按鈕時,會被重定向到 GitHub 登入頁面,授權完成後重定向回你的應用。

// 用戶點擊時重定向到 GitHub OAuth 登入頁面
function redirectToGitHubOAuth() {
    const clientId = '你的-client-id'; // 使用你在 GitHub 取得的 Client ID
    const redirectUri = 'http://localhost:3000/callback'; // 你設定的重定向 URI
    const scope = 'repo'; // 設置權限範圍,如存取所有儲存庫

    const authUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}`;
    window.location.href = authUrl;
}

步驟 2:處理 OAuth 回調並獲取存取令牌

當 GitHub 重定向回你的應用後,你需要將 code 發送到你的伺服器(或直接在前端處理,取決於應用設計),以獲得存取令牌。

// OAuth 回調處理邏輯
function handleOAuthCallback() {
    const urlParams = new URLSearchParams(window.location.search);
    const code = urlParams.get('code');

    if (code) {
        // 將 'code' 發送到伺服器換取存取令牌
        fetch('https://your-server.com/oauth/callback', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ code }),
        })
        .then(response => response.json())
        .then(data => {
            // 存儲存取令牌,後續請求中需要
            const accessToken = data.access_token;
            localStorage.setItem('github_token', accessToken);
            loadRepositories();
        });
    }
}

步驟 3:顯示使用者的 GitHub 儲存庫列表

透過 GitHub API 和存取令牌來取得使用者的儲存庫列表。

// 使用存取令牌從 GitHub API 獲取使用者儲存庫列表
function loadRepositories() {
    const token = localStorage.getItem('github_token');

    fetch('https://api.github.com/user/repos', {
        headers: {
            Authorization: `Bearer ${token}`
        }
    })
    .then(response => response.json())
    .then(repos => {
        const repoList = document.getElementById('repo-list');
        repoList.innerHTML = '';  // 清空列表

        repos.forEach(repo => {
            const listItem = document.createElement('li');
            listItem.innerHTML = `<a href="#" onclick="loadCommits('${repo.full_name}')">${repo.name}</a>`;
            repoList.appendChild(listItem);
        });
    });
}

步驟 4:顯示指定儲存庫的提交紀錄

點選儲存庫名稱後,載入並顯示提交紀錄。

// 根據選定儲存庫的名稱載入其提交紀錄
function loadCommits(repoFullName) {
    const token = localStorage.getItem('github_token');

    fetch(`https://api.github.com/repos/${repoFullName}/commits`, {
        headers: {
            Authorization: `Bearer ${token}`
        }
    })
    .then(response => response.json())
    .then(commits => {
        const commitList = document.getElementById('commit-list');
        commitList.innerHTML = '';  // 清空提交紀錄列表

        commits.forEach(commit => {
            const listItem = document.createElement('li');
            listItem.innerHTML = `${commit.commit.author.name}: ${commit.commit.message}`;
            commitList.appendChild(listItem);
        });
    });
}

步驟 5:管理儲存庫的 Issue

你可以讓使用者查看、建立或更新儲存庫中的 issue。

// 取得儲存庫的所有 issue
function loadIssues(repoFullName) {
    const token = localStorage.getItem('github_token');

    fetch(`https://api.github.com/repos/${repoFullName}/issues`, {
        headers: {
            Authorization: `Bearer ${token}`
        }
    })
    .then(response => response.json())
    .then(issues => {
        const issueList = document.getElementById('issue-list');
        issueList.innerHTML = '';  // 清空 issue 列表

        issues.forEach(issue => {
            const listItem = document.createElement('li');
            listItem.innerHTML = `${issue.title}: ${issue.body}`;
            issueList.appendChild(listItem);
        });
    });
}

// 建立新 issue
function createIssue(repoFullName, issueTitle, issueBody) {
    const token = localStorage.getItem('github_token');

    fetch(`https://api.github.com/repos/${repoFullName}/issues`, {
        method: 'POST',
        headers: {
            Authorization: `Bearer ${token}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            title: issueTitle,
            body: issueBody
        })
    })
    .then(response => response.json())
    .then(issue => {
        alert(`Issue created: ${issue.title}`);
        loadIssues(repoFullName);  // 更新 issue 列表
    });
}

步驟 6:前端 UI 設計

你可以使用 Bootstrap 或其他前端框架來建立一個簡單易用的 UI:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GitHub Repo Manager</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
    <script defer src="app.js"></script>
</head>
<body>
    <div class="container">
        <h1>GitHub 程式碼管理系統</h1>
        <button class="btn btn-primary" onclick="redirectToGitHubOAuth()">登入 GitHub</button>

        <h2>你的儲存庫</h2>
        <ul id="repo-list"></ul>

        <h3>提交紀錄</h3>
        <ul id="commit-list"></ul>

        <h3>Issue 列表</h3>
        <ul id="issue-list"></ul>
    </div>
</body>
</html>

說明:

  1. OAuth 認證:我們使用 GitHub 的 OAuth 流程來讓使用者授權應用存取其儲存庫資料。
  2. API 互動:透過 GitHub API,可以輕鬆地獲取儲存庫、提交紀錄和 issue,並可以動態管理它們。
  3. 資料顯示:我們使用簡單的 HTML 和 Bootstrap 來顯示從 API 獲取的資料。

1. OAuth 認證登錄流程 (redirectToGitHubOAuth 函數)

這段程式碼的目的是引導使用者到 GitHub OAuth 登錄頁面,請求授權來存取其 GitHub 帳戶的資料。

function redirectToGitHubOAuth() {
    const clientId = '你的-client-id'; // 使用你在 GitHub 取得的 Client ID
    const redirectUri = 'http://localhost:3000/callback'; // 你設定的重定向 URI
    const scope = 'repo'; // 設置權限範圍,如存取所有儲存庫

    const authUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}`;
    window.location.href = authUrl;
}

解釋:

  1. clientId:這是你在 GitHub 開發者設定中註冊的 OAuth 應用程式時,GitHub 提供的客戶端 ID。這個 ID 會識別你的應用程式。
  2. redirectUri:這是使用者授權後,GitHub 將其重定向的 URL,應該是你應用程式的某個 URL。當使用者授權後,GitHub 會將授權碼(code)發送到這個 URI。
  3. scope:表示你希望存取的 GitHub 資料範圍,例如 repo 代表儲存庫相關的資料。
  4. window.location.href:這行程式碼會將使用者導向到 GitHub OAuth 認證頁面。

當使用者同意授權後,GitHub 會將使用者重定向回你的應用程式,並附帶授權碼。


2. 處理 OAuth 回調 (handleOAuthCallback 函數)

當使用者從 GitHub 重定向回你的應用程式時,這個函數會處理回調中的授權碼,並用該授權碼換取存取令牌。

function handleOAuthCallback() {
    const urlParams = new URLSearchParams(window.location.search);
    const code = urlParams.get('code');

    if (code) {
        fetch('https://your-server.com/oauth/callback', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ code }),
        })
        .then(response => response.json())
        .then(data => {
            const accessToken = data.access_token;
            localStorage.setItem('github_token', accessToken);
            loadRepositories();
        });
    }
}

解釋:

  1. urlParams:這段程式碼用來從 URL 中擷取查詢參數,並取得 GitHub 發送回來的授權碼(code)。
  2. fetch:將授權碼發送到後端伺服器,後端伺服器會用該授權碼請求存取令牌(access_token)。
  3. localStorage.setItem:將從 GitHub 獲取的 access_token 存儲在瀏覽器的 localStorage 中,供後續的 API 請求使用。
  4. loadRepositories:當成功獲得存取令牌後,自動載入使用者的儲存庫列表。

3. 取得使用者儲存庫 (loadRepositories 函數)

這個函數使用 GitHub API 來取得使用者的儲存庫列表,並顯示在網頁上。

function loadRepositories() {
    const token = localStorage.getItem('github_token');

    fetch('https://api.github.com/user/repos', {
        headers: {
            Authorization: `Bearer ${token}`
        }
    })
    .then(response => response.json())
    .then(repos => {
        const repoList = document.getElementById('repo-list');
        repoList.innerHTML = '';  // 清空列表

        repos.forEach(repo => {
            const listItem = document.createElement('li');
            listItem.innerHTML = `<a href="#" onclick="loadCommits('${repo.full_name}')">${repo.name}</a>`;
            repoList.appendChild(listItem);
        });
    });
}

解釋:

  1. localStorage.getItem('github_token'):從 localStorage 中獲取存取令牌。
  2. fetch:向 GitHub API 發送 GET 請求來獲取使用者的儲存庫列表。API URL 是 https://api.github.com/user/repos,而存取令牌被作為 Authorization 標頭的一部分發送(Bearer 認證模式)。
  3. repos:API 回應的是一個儲存庫的列表。
  4. repoList.innerHTML = '';:清空現有的列表。
  5. forEach:遍歷回應的儲存庫列表,並將每個儲存庫添加到頁面上作為連結。點擊連結時會加載該儲存庫的提交紀錄。

4. 載入儲存庫提交紀錄 (loadCommits 函數)

當使用者點擊某個儲存庫名稱時,這個函數會使用 GitHub API 來載入該儲存庫的提交紀錄。

function loadCommits(repoFullName) {
    const token = localStorage.getItem('github_token');

    fetch(`https://api.github.com/repos/${repoFullName}/commits`, {
        headers: {
            Authorization: `Bearer ${token}`
        }
    })
    .then(response => response.json())
    .then(commits => {
        const commitList = document.getElementById('commit-list');
        commitList.innerHTML = '';  // 清空提交紀錄列表

        commits.forEach(commit => {
            const listItem = document.createElement('li');
            listItem.innerHTML = `${commit.commit.author.name}: ${commit.commit.message}`;
            commitList.appendChild(listItem);
        });
    });
}

解釋:

  1. repoFullName:儲存庫的完整名稱(包括擁有者和儲存庫名稱),例如 username/repository
  2. fetch:這裡我們使用 GitHub API 來取得特定儲存庫的提交紀錄。API URL 是 https://api.github.com/repos/${repoFullName}/commits
  3. commits:API 回應的是該儲存庫的提交紀錄列表。
  4. forEach:遍歷提交紀錄,將每個提交的作者名稱和提交訊息顯示在頁面上。

5. 管理儲存庫的 Issue (loadIssuescreateIssue 函數)

這兩個函數分別用於載入儲存庫的 issue 和建立新的 issue。

載入 Issue 列表:

function loadIssues(repoFullName) {
    const token = localStorage.getItem('github_token');

    fetch(`https://api.github.com/repos/${repoFullName}/issues`, {
        headers: {
            Authorization: `Bearer ${token}`
        }
    })
    .then(response => response.json())
    .then(issues => {
        const issueList = document.getElementById('issue-list');
        issueList.innerHTML = '';  // 清空 issue 列表

        issues.forEach(issue => {
            const listItem = document.createElement('li');
            listItem.innerHTML = `${issue.title}: ${issue.body}`;
            issueList.appendChild(listItem);
        });
    });
}

建立新 Issue:

function createIssue(repoFullName, issueTitle, issueBody) {
    const token = localStorage.getItem('github_token');

    fetch(`https://api.github.com/repos/${repoFullName}/issues`, {
        method: 'POST',
        headers: {
            Authorization: `Bearer ${token}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            title: issueTitle,
            body: issueBody
        })
    })
    .then(response => response.json())
    .then(issue => {
        alert(`Issue created: ${issue.title}`);
        loadIssues(repoFullName);  // 更新 issue 列表
    });
}

解釋:

  1. loadIssues:這個函數用來從 GitHub API 中獲取儲存庫的所有 issue,並顯示在頁面上。
  2. createIssue:這個函數用來建立新 issue。使用 POST 方法向 GitHub API 發送請求,並在主體中傳送 issue 的標題和內容。

6. 前端 UI 介面

最後

,這段程式碼包含了簡單的前端 HTML,用來顯示儲存庫、提交紀錄和 issue。

<ul id="repo-list"></ul>
<ul id="commit-list"></ul>
<ul id="issue-list"></ul>

解釋:

  1. repo-list:用來顯示使用者的 GitHub 儲存庫列表。
  2. commit-list:用來顯示儲存庫的提交紀錄。
  3. issue-list:用來顯示儲存庫的 issue。

總結

這個程式碼展示了如何使用 GitHub OAuth 來實現授權,並透過 GitHub API 獲取使用者的儲存庫、提交紀錄和 issue。

  1. 使用 GitHub OAuth 進行授權登錄。
  2. 授權後,取得存取令牌並保存。
  3. 使用存取令牌來訪問 GitHub API,顯示儲存庫、提交紀錄和 issue。

上一篇
day 24 javascript自動整理筆記網頁程式管理系統
系列文
Javascript網頁程式管理系統25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言